package com.wctj.api.security.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.*;

/**
 * @Description: HeaderMapRequestWrapper
 * @author carol
 **/
@Slf4j
public class HeaderMapRequestWrapper extends HttpServletRequestWrapper {


    private final Map<String, Object> headerMap = new HashMap<>();


    /**
     * construct a wrapper for this request
     *
     * @param request
     */
    public HeaderMapRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
    }

    /**
     * add a header with given name and value
     *
     * @param name
     * @param value
     */
    public void addHeader(String name, Object value) {
        headerMap.put(name, value);
    }

    /**
     * add all headers with map
     *
     * @param headers
     */
    public void addHeaders(Map<String,String> headers) {
        headerMap.putAll(headers);
    }

    @Override
    public String getHeader(String name) {
        String headerValue = super.getHeader(name);
        log.debug("Get header from HttpServletRequestWrapper,name:{},value:{}", name, headerValue);
        if (StringUtils.isBlank(headerValue)) {
            for (Map.Entry<String,Object> header : headerMap.entrySet()) {
                if (header.getKey().equalsIgnoreCase(name)) {
                    headerValue =  Objects.nonNull(header.getValue()) ? header.getValue().toString() : null;
                    log.debug("Get header from own wrapper,name:{},value:{}", name, headerValue);
                    break;
                }
            }
        }
        return headerValue;
    }

    @Override
    public int getIntHeader(String name) {
        // when header is null, getIntHeader will be return -1
        String value = getHeader(name);
        if (value == null) {
            return -1;
        }
        return Integer.parseInt(value);
    }


    /**
     * get the Header names
     */
    @Override
    public Enumeration<String> getHeaderNames() {
        List<String> names = Collections.list(super.getHeaderNames());
        for (String name : headerMap.keySet()) {
            if (names.contains(name)){
                continue;
            }
            names.add(name);
        }
        return Collections.enumeration(names);
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        final Enumeration<String> headers = super.getHeaders(name);
        List<String> values = Collections.list(headers);
        if (headerMap.containsKey(name) || headerMap.containsKey(name.toLowerCase())) {
            values = Collections.singletonList(Optional.ofNullable(headerMap.getOrDefault(name, headerMap.get(name.toLowerCase()))).orElse("").toString());
        }
        return Collections.enumeration(values);
    }


}
